package com.topscomm.mis.cbb.pm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.cbo.pojo.CboApprovalFlowInsEntity;
import com.topscomm.cbo.pojo.CboApprovalLineEntity;
import com.topscomm.cbo.pojo.CboApprovalNodeEntity;
import com.topscomm.cbo.pojo.CboUserEntity;
import com.topscomm.cbo.service.ICboApprovalFlowInsService;
import com.topscomm.cbo.service.ICboApprovalLineService;
import com.topscomm.cbo.service.ICboApprovalNodeService;
import com.topscomm.cbo.service.ICboUserService;
import com.topscomm.mis.cbb.pm.api.ITaskService;
import com.topscomm.mis.cbb.pm.api.IWbsService;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmTaskEntity;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmWbsChangeEntity;
import com.topscomm.mis.cbb.pm.base.pojo.CbbPmWbsEntity;
import com.topscomm.mis.cbb.pm.base.service.impl.CbbPmTaskService;
import com.topscomm.mis.cbb.pm.base.service.impl.CbbPmWbsChangeService;
import com.topscomm.mis.cbb.pm.base.service.impl.CbbPmWbsService;
import com.topscomm.mis.cbb.pm.service.abs.AbstractWbsService;
import com.topscomm.mis.cbb.pm.util.FlowNode;
import com.topscomm.mis.cbb.pm.util.PmSystemConst;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.topscomm.mis.cbb.pm.util.PmSystemConst.DEFAULTPARENTCODE;

@Slf4j
@Service
public class WbsService extends AbstractWbsService {
    @Autowired
    private CbbPmWbsService cbbPmWbsService;
    @Autowired
    private CbbPmTaskService cbbPmTaskService;
    @Autowired
    private ICboApprovalNodeService cboApprovalNodeService;
    @Autowired
    private ICboApprovalLineService cboApprovalLineService;
    @Autowired
    private ICboApprovalFlowInsService cboApprovalFlowInsService;
    @Autowired
    private ITaskService taskService;
    @Autowired
    private IWbsService wbsService;
    @Autowired
    private ICboUserService cboUserService;
    @Autowired
    private CbbPmWbsChangeService cbbPmWbsChangeService;

    //序号
    public static String INDEX = "index";


    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:wbs变更
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeWbs(Map<String, Object> paraMap) {
        // 如果没传必传参数，告诉原函数返回空
        if(!paraMap.containsKey("uuCode") && !paraMap.containsKey("flowId")
                && !paraMap.containsKey("sourceId") && !paraMap.containsKey("sourceType")) {
            throw new ServiceException("必传参数未传！");
        }
        String flowId = ConvertUtil.convertToString(paraMap.get("flowId"));
        String sourceId = ConvertUtil.convertToString(paraMap.get("sourceId"));
        String sourceType = ConvertUtil.convertToString(paraMap.get("sourceType"));
        String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));

    };

    /**
     * @author: hudeyong
     * @date: 2023-06-13
     * @description:创建wbs
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void operateWbs(Map<String, Object> paraMap) {
        if(!paraMap.containsKey("operateType")){
            return;
        }
        // 操作类型，1创建WBS、2创建子流程的WBS、3变更WBS、4流程继续走更新WBS
        int operateType = ConvertUtil.convertToInt(paraMap.get("operateType"));
        CbbPmWbsEntity pmWbsEntity = new CbbPmWbsEntity();
        String parentCode = DEFAULTPARENTCODE;
        if(operateType == PmSystemConst.OperateWbsType.CREATE) {
            // 创建wbs-必传参数uuCode、flowId、sourceId、sourceType,flowInsId
            createWbs(paraMap, pmWbsEntity);
            initTask(paraMap, pmWbsEntity, parentCode,0, 0);
        } else if(operateType == PmSystemConst.OperateWbsType.CREATESONFLOW){
            // 创建wbs下的子流程-必传参数uuCode、flowId、sourceId、sourceType、parentNodeId,flowInsId
//            createWbsSon(paraMap, pmWbsEntity, parentCode);
            if(!paraMap.containsKey("uuCode") || !paraMap.containsKey("parentNodeId") && !paraMap.containsKey("flowId")
                    && !paraMap.containsKey("sourceId") && !paraMap.containsKey("sourceType")) {
                throw new ServiceException("必传参数未传！");
            }
            String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));
            StringBufferProxy sql = new StringBufferProxy();
            sql.appendSingle("{0} = '{1}'",CbbPmWbsEntity.FieldProjectuucode,uuCode);
            List<CbbPmWbsEntity> pmWbsEntities = cbbPmWbsService.queryByWhere(sql.toString());
            if(pmWbsEntities == null || pmWbsEntities.size()==0){
                throw new ServiceException("未找到主流程WBS！");
            }
            pmWbsEntity = pmWbsEntities.get(0);
            sql.clear();
            int useTimes = 0;
            sql.appendSingle("{0} = '{1}' and {2} = '{3}'",
                    CbbPmTaskEntity.FieldNodeid,ConvertUtil.convertToString(paraMap.get("parentNodeId")),
                    CbbPmTaskEntity.FieldProjectuucode,uuCode);
            if(paraMap.containsKey("useTimes")){
                useTimes = ConvertUtil.convertToInt(paraMap.get("useTimes"));
                sql.appendSingle(" and {0} = '{1}'", CbbPmTaskEntity.FieldUsetimes,useTimes);
            }
            sql.appendSingle(" ORDER BY ROUND DESC");
            List<CbbPmTaskEntity> pmTaskEntities = cbbPmTaskService.queryByWhere(sql.toString());
            if (pmTaskEntities.size()==0 || pmWbsEntities == null) {
                throw new ServiceException("未找到主任务！");
            }
            parentCode = pmTaskEntities.get(0).getCode();
            int loopTimes = ConvertUtil.convertToInt(paraMap.get("loopTimes"));
            initTask(paraMap, pmWbsEntity, parentCode,loopTimes,useTimes);
        } else if(operateType == PmSystemConst.OperateWbsType.CHANGECOMMIT) {
            //  约束条件变更（从头开始到结束）-必传参数uuCode、flowId、sourceId、sourceType
            // todo 最后做，等设计
//            changeTaskByCommit(nodeList, paraMap);
        } else if(operateType == PmSystemConst.OperateWbsType.CHANGENODE) {
            // 流程节点变更nodeId
            changeTaskByNode(paraMap);
        } else if(operateType == PmSystemConst.OperateWbsType.CHANGEFLOW) {
            // 流程变更-必传参数flowId、sourceType
            changeTaskByFlow(paraMap);
        } else if (operateType == PmSystemConst.OperateWbsType.BACKNODE) {
            // 流程变更-必传参数startNodeId，endNodeId,uuCode,flowInsId、flowId、sourceId、sourceType
            changeTaskByNodeBack(paraMap);
        } else if (operateType == PmSystemConst.OperateWbsType.BACKFLOW) {
            // 流程变更退回流程-必传参数uuCode
            changeTaskByFlowBack(paraMap);
            return;
        } else if (operateType == PmSystemConst.OperateWbsType.CONTINUEFLOW) {
            // 流程继续往后走-必传参数 startNodeId,uuCode,flowId,sourceId、sourceType,flowInsId
            continueFlow(paraMap);
            return;
        }
        //将修改的wbs中进行中的节点任务设为待进行
        StringBufferProxy sql = new StringBufferProxy();
        if(paraMap.containsKey("uuCode")){
            sql.appendSingle("UPDATE CBB_PM_TASK SET STATUS = '{0}' WHERE",PmSystemConst.TaskStatus.READYSTART);
            sql.appendSingle(" projectuucode = '{0}' AND STATUS = '{1}' and flowInsId = '{2}'",
                    ConvertUtil.convertToString(paraMap.get("uuCode")),PmSystemConst.TaskStatus.NOTSTART,ConvertUtil.convertToString(paraMap.get("flowInsId")));
            sql.appendSingle(" AND NODEID IN (SELECT NODEID FROM CBOAPPROVALNODEINS WHERE FLOWINSID = {0} AND STATE = 1)",
                    ConvertUtil.convertToString(paraMap.get("flowInsId")));
            cbbPmTaskService.updateExecute(sql.toString());
        } else{
            sql.appendSingle("UPDATE CBB_PM_TASK SET STATUS = '{0}' WHERE NODEID IN (SELECT NODEID FROM CBOAPPROVALNODEINS WHERE STATE = 1 AND SOURCETYPE = '{1}') ",
                    PmSystemConst.TaskStatus.READYSTART,ConvertUtil.convertToString(paraMap.get("sourceType")));
        }
    }
    /**
     * @author: hudeyong
     * @date: 2023-07-18
     * @description:继续流程
     * 必传：uuCode
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void continueFlow(Map<String, Object> paraMap) {
        // 不包含开始节点的节点list
        paraMap.put("includeStart",false);
        List<FlowNode> nodeList = queryWbsNodeList(paraMap);
        String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));
        String flowInsId = ConvertUtil.convertToString(paraMap.get("flowInsId"));
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0} = '{1}'",CbbPmWbsEntity.FieldProjectuucode,uuCode);
        List<CbbPmWbsEntity> pmWbsEntities = cbbPmWbsService.queryByWhere(sql.toString());
        if(pmWbsEntities.size()==0){
            throw new ServiceException("未找到WBS！");
        }
        CbbPmWbsEntity cbbPmWbsEntity = pmWbsEntities.get(0);
        //备份
        Map<String,Object> pmWbsInfo = cbbPmWbsEntity.convertToMap();
        sql.clear();
        sql.appendSingle("nodeid = '{0}' and FLOWINSID = '{1}'",ConvertUtil.convertToString(paraMap.get("startNodeId")),flowInsId);
        List<CbbPmTaskEntity> pmTaskList = cbbPmTaskService.queryByWhere(sql.toString());
        String parentCode = findMultipleNodeParentCode(pmTaskList);
//        for(FlowNode node : nodeList){
//            System.out.println(node.getName() + "---"+ node.getPlanUser());
//        }
        // 同步执行
        List<FlowNode> syncNodeList = nodeList.stream().filter( e -> (PmSystemConst.NodeRunType.SYNC.equals(e.getRuntype()))).collect(Collectors.toList());
        if(syncNodeList.size()>0){
            taskService.changeTaskByFlow(uuCode,syncNodeList,pmWbsInfo,parentCode,flowInsId);
        }
        // 异步执行
        nodeList.removeAll(syncNodeList);
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 在这里执行耗时操作
                if(nodeList.size()>0){
                    taskService.changeTaskByFlow(uuCode,nodeList,pmWbsInfo,parentCode,flowInsId);
                }
                // 取消删除的节点
                paraMap.remove("startNodeId");
                paraMap.remove("endNodeId");
                List<FlowNode> nodeList = queryWbsNodeList(paraMap);
                taskService.loseTask(nodeList,true,uuCode,flowInsId);
            }
        }).start();
        }
    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:任务变更--退回流程
     * 必传：uuCode
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeTaskByFlowBack(Map<String, Object> paraMap) {
        String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0} = '{1}'",CbbPmWbsEntity.FieldProjectuucode,uuCode);
        List<CbbPmWbsEntity> pmWbsEntities = cbbPmWbsService.queryByWhere(sql.toString());
        CbbPmWbsEntity cbbPmWbsEntity = pmWbsEntities.get(0);
        //备份
        CbbPmWbsChangeEntity cbbPmWbsChangeEntity = updateWbs(cbbPmWbsEntity);
        Map<String,Object> pmWbsChangeInfo = cbbPmWbsChangeEntity.convertToMap();
        taskService.backupTask(sql.toString(),pmWbsChangeInfo);
        //删除
        cbbPmWbsService.deleteByWhere(sql.toString());
        cbbPmTaskService.deleteByWhere(sql.toString());
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:任务变更--退回
     * 必传：startNodeId，endNodeId,uuCode,flowInsId、flowId、sourceId、sourceType
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeTaskByNodeBack(Map<String, Object> paraMap) {
        String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));
        String flowInsId = ConvertUtil.convertToString(paraMap.get("flowInsId"));
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0} = '{1}'", CbbPmWbsEntity.FieldProjectuucode,uuCode);
        List<CbbPmWbsEntity> pmWbsEntities = cbbPmWbsService.queryByWhere(sql.toString());
        if(pmWbsEntities.size() == 0) {
            return;
        }
        CbbPmWbsEntity cbbPmWbsEntity = pmWbsEntities.get(0);
        //更新wbs
        CbbPmWbsChangeEntity cbbPmWbsChangeEntity = updateWbs(cbbPmWbsEntity);
        Map<String,Object> pmWbsChangeInfo = cbbPmWbsChangeEntity.convertToMap();
        // 获取start-end的节点状态
        List<FlowNode> nodeList = queryWbsNodeList(paraMap);
        //这个范围的任务备份，进行或待进行的任务关闭
        String nodeIds = nodeList.stream().map(item ->"'" + item.getId() + "'").collect(Collectors.joining(","));
        //备份
        sql.clear();
        sql.appendSingle(" PROJECTUUCODE = '{0}' and nodeid in ({1}) and flowInsId = '{2}'",uuCode,nodeIds,flowInsId);
        List<CbbPmTaskEntity> taskList = cbbPmTaskService.queryByWhere(sql.toString());
        taskService.backupTask(sql.toString(),pmWbsChangeInfo);
        //关闭
        sql.clear();
        sql.appendSingle("UPDATE CBB_PM_TASK SET STATUS = '{0}',currently=0 WHERE STATUS in ('0','1','2','5') and PROJECTUUCODE = '{1}' and nodeid in ({2}) and flowInsId = '{3}'",
                PmSystemConst.TaskStatus.BACK,uuCode,nodeIds,flowInsId);
        cbbPmTaskService.updateExecute(sql.toString());
        //新增这个范围的任务，轮次加1
        //查询开始节点的parentcode
        String parentCode = findMultipleNodeParentCode(taskList);

        // 同步执行
//        List<FlowNode> syncNodeList = nodeList.stream().filter( e -> (PmSystemConst.NodeRunType.SYNC.equals(e.getRuntype()))).collect(Collectors.toList());
        // 异步执行
//        nodeList.removeAll(syncNodeList);
        int loopTimes = ConvertUtil.convertToInt(paraMap.get("loopTimes"));
        int useTimes = ConvertUtil.convertToInt(paraMap.get("useTimes"));
        taskService.initFlowTask(paraMap, nodeList,cbbPmWbsEntity.convertToMap(),parentCode,flowInsId,true, loopTimes, useTimes);
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 在这里执行耗时操作
                // 重新生成这个范围的人工任务
                createArtificialTask(nodeIds,uuCode,flowInsId,taskList);
            }
        }).start();

    }

    /**
     * @author: hudeyong
     * @date: 2023-06-30
     * @description:重新生成人工任务
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void createArtificialTask(String nodeIds, String uuCode, String flowInsId, List<CbbPmTaskEntity> oldTaskList) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("PROJECTUUCODE = '{0}' and nodeid in ({1}) and flowInsId = '{2}'",
                uuCode,nodeIds,flowInsId);
        List<CbbPmTaskEntity> cbbPmTaskEntities = cbbPmTaskService.queryByWhere(sql.toString());
        List<CbbPmTaskEntity> artificialTaskList = cbbPmTaskEntities.stream().filter(item -> PmSystemConst.TaskSource.ARTIFICIAL == item.getSource()).collect(Collectors.toList());
        cbbPmTaskEntities.removeAll(artificialTaskList);
        List<BasicEntity> rtificialTaskList = new ArrayList<>();
        for (CbbPmTaskEntity pmTaskEntity : artificialTaskList) {
            // 先找到以前的上级
            List<CbbPmTaskEntity> oldParentTask = oldTaskList.stream().filter(item -> item.getCode().equals(pmTaskEntity.getParentcode())).collect(Collectors.toList());
            if(oldParentTask.size()==0){
                continue;
            }
            // 找到以前的对应现在的
            List<CbbPmTaskEntity> tempList = cbbPmTaskEntities.stream().filter(item ->
                    item.getNodeid().equals(oldParentTask.get(0).getNodeid()) &&
                            item.getResponsibleusercode().equals(oldParentTask.get(0).getResponsibleusercode())
            ).collect(Collectors.toList());
            if(tempList.size()==0){
                continue;
            }
            pmTaskEntity.setParentcode(tempList.get(0).getCode());
            pmTaskEntity.setNodeinsid("");
            pmTaskEntity.setRound(pmTaskEntity.getRound()+1);
            long[] arrayId = PrimaryKeyUtil.GeneIDs(pmTaskEntity.getTableName(), 1);
            pmTaskEntity.setId(arrayId[0]);
            pmTaskEntity.setStatus(PmSystemConst.TaskStatus.NOTSTART);
            rtificialTaskList.add(pmTaskEntity);
        }
        cbbPmTaskService.insertBatch(rtificialTaskList);
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:获取多个node下任务的parentcode
     * @modify:
     */
    public String findMultipleNodeParentCode(List<CbbPmTaskEntity> taskList) {
        String parentCode = DEFAULTPARENTCODE;
        Set<String> parentCodeSet = new HashSet<>();
        // 获取所有parentCode
        for (CbbPmTaskEntity task : taskList) {
            parentCodeSet.add(task.getParentcode());
        }
        // 去除code在 parentCodeSet 中的数据
        for (CbbPmTaskEntity task : taskList) {
            if(parentCodeSet.contains(task.getCode())) {
                parentCodeSet.remove(task.getCode());
            }
        }
        Iterator<String> iterator = parentCodeSet.iterator();
        while (iterator.hasNext()) {
            return iterator.next();
        }
        return parentCode;
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:任务变更--节点
     * @modify:
     */
    public void changeTaskByNode(Map<String, Object> paraMap) {
        String nodeId = ConvertUtil.convertToString(paraMap.get("nodeId"));
        List<Map<String,Object>> wbsList = cboApprovalFlowInsService.queryMap(paraMap,"queryRuningWbsByNode");
        StringBufferProxy sql = new StringBufferProxy();
        for(Map<String,Object> wbsInfo : wbsList) {
            sql.clear();
            sql.appendSingle("id in (SELECT FLOWINSID FROM CBB_PM_TASK WHERE NODEID = '{0}' AND PROJECTUUCODE = '{1}' GROUP BY FLOWINSID)",
                    nodeId,ConvertUtil.convertToString(wbsInfo.get(CbbPmWbsEntity.FieldProjectuucode)));
            List<CboApprovalFlowInsEntity> approvalFlowInsEntities = cboApprovalFlowInsService.queryByWhere(sql.toString());
            if (approvalFlowInsEntities.size()==0) {
                continue;
            }
            paraMap.put("flowId",approvalFlowInsEntities.get(0).getFlowid());
            paraMap.put("sourceId",approvalFlowInsEntities.get(0).getSourceid());
            paraMap.put("sourceType",approvalFlowInsEntities.get(0).getSourcetype());
            paraMap.put("flowInsId",approvalFlowInsEntities.get(0).getId());
            List<FlowNode> nodeList = queryWbsNodeList(paraMap);
            FlowNode node = new FlowNode();
            for(FlowNode nodeInfo : nodeList) {
                if(nodeInfo.getId().equals(nodeId)){
                    node = nodeInfo;
                    break;
                }
            }
            //changeTaskList, FlowNode nodeInfo, CbbPmWbsEntity pmWbsEntity,String parentCode, String flowInsId)
//            changeTask(List<CbbPmTaskEntity> changeTaskList, FlowNode nodeInfo, CbbPmWbsEntity pmWbsEntity,String parentCode, String flowInsId)
            taskService.changeTaskByNode(wbsInfo,node,paraMap);
        }

    }

    public CbbPmWbsChangeEntity updateWbs(CbbPmWbsEntity cbbPmWbsEntity){
        // 插入wbs变更记录
        CbbPmWbsChangeEntity cbbPmWbsChangeEntity = new CbbPmWbsChangeEntity();
        cbbPmWbsChangeEntity.setProjectuucode(cbbPmWbsEntity.getProjectuucode());
        cbbPmWbsChangeEntity.setWbscode(cbbPmWbsEntity.getWbscode());
        cbbPmWbsChangeEntity.setChangetype(PmSystemConst.WbsChangeType.AUTOMATIC);
        cbbPmWbsChangeEntity.setChangereason("流程变更引起WBS变更");
        cbbPmWbsChangeEntity.setBeforeversion(cbbPmWbsEntity.getVersion());
        cbbPmWbsChangeEntity.setAfterversion(cbbPmWbsEntity.getVersion()+1);
        long[] arrayId = PrimaryKeyUtil.GeneIDs(cbbPmWbsChangeEntity.getTableName(), 1);
        cbbPmWbsChangeEntity.setId(arrayId[0]);
        cbbPmWbsChangeService.insert(cbbPmWbsChangeEntity);
        // wbs版本号加1
        cbbPmWbsEntity.setVersion(cbbPmWbsEntity.getVersion()+1);
        cbbPmWbsService.updateEntity(cbbPmWbsEntity);
        return cbbPmWbsChangeEntity;
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:任务变更--流程
     * @modify:
     */
    public void changeTaskByFlow(Map<String, Object> paraMap){
        //flowId、sourceType
        String flowId = ConvertUtil.convertToString(paraMap.get("flowId"));
        String sourceType = ConvertUtil.convertToString(paraMap.get("sourceType"));
        StringBufferProxy sql = new StringBufferProxy();
        //找到改流程正在审批的数据
//        sql.appendSingle("{0} = '{1}' and {2} = '{3}' and state = '1'",
//                CboApprovalFlowInsEntity.FieldFlowid,flowId,CboApprovalFlowInsEntity.FieldSourcetype,sourceType);
        List<Map<String,Object>> wbsList = cbbPmTaskService.queryMap(paraMap,"queryRuningWbs");
        for(Map<String,Object> wbsInfo : wbsList) {
            sql.clear();
            sql.appendSingle("SELECT PARENTCODE FROM CBB_PM_TASK WHERE FLOWID = {0} AND SOURCE = '{1}'" +
                    " AND PARENTCODE IN (SELECT code FROM CBB_PM_TASK WHERE FLOWID != '{0}' AND SOURCE = '{1}') GROUP BY PARENTCODE ",
                    flowId, PmSystemConst.TaskSource.FLOW);
            List<Map<String,Object>> parentCodeList = cbbPmWbsService.selectExecute(sql.toString());
            String parentCode = DEFAULTPARENTCODE;
            if(parentCodeList.size()>0){
                parentCode = ConvertUtil.convertToString(parentCodeList.get(0).get("parentcode"));
            }
            String sourceId = ConvertUtil.convertToString(wbsInfo.get("sourceid"));
            String flowInsId = ConvertUtil.convertToString(wbsInfo.get("flowinsid"));
            paraMap.put("sourceId",sourceId);
            paraMap.put("flowInsId",flowInsId);
            CbbPmWbsEntity cbbPmWbsEntity = new CbbPmWbsEntity();
            cbbPmWbsEntity.convertFromMap(wbsInfo);
            // 插入wbs变更记录
            CbbPmWbsChangeEntity cbbPmWbsChangeEntity = updateWbs(cbbPmWbsEntity);
            //查找进行中的流程任务
            sql.clear();
            sql.appendSingle("SELECT NODEID FROM CBB_PM_TASK WHERE {0} = '{1}' AND {2} =  {3} AND {4} = {5} GROUP BY NODEID ",
                    CbbPmTaskEntity.FieldProjectuucode,cbbPmWbsEntity.getProjectuucode(),
                    CbbPmTaskEntity.FieldSource, PmSystemConst.TaskSource.FLOW,
                    CbbPmTaskEntity.FieldStatus, PmSystemConst.TaskStatus.RUNNING);
            List<Map<String, Object>> pmRuningTaskList = cbbPmTaskService.selectExecute(sql.toString());
            // 获取进行中任务为开始节点的node
            // todo
            List<FlowNode> tempNodeList = new ArrayList<>();
            for(Map<String, Object> map : pmRuningTaskList) {
                String startNodeId = ConvertUtil.convertToString(map.get("nodeid"));
                paraMap.put("startNodeId",startNodeId);
                tempNodeList.addAll(queryWbsNodeList(paraMap));
            }
            // 剔除重复的数据
            List<FlowNode> nodeList = new ArrayList<>();
            Set<Object> idSet = new HashSet<>();
            for(FlowNode node : tempNodeList){
                String id = node.getId();
                if (!idSet.contains(id)) {
                    nodeList.add(node);
                    idSet.add(id);
                }
            }
            //nodeList中node相关的任务需要重新生成，其他的直接备份即可
            //生成快照
            //List<FlowNode> nodeList, String uuCode, CbbPmWbsChangeEntity wbsChangeEntity
            Map<String,Object> pmWbsChangeInfo = cbbPmWbsChangeEntity.convertToMap();
            sql.clear();
            sql.appendSingle("projectuucode = '{0}' and source = '{1}'",
                    cbbPmWbsChangeEntity.getProjectuucode(), PmSystemConst.TaskSource.FLOW);
            taskService.backupTask(sql.toString(),pmWbsChangeInfo);
            //重新生成任务并进行比对
//            changeTaskByFlow(String uuCode, List<FlowNode> nodeList, Map<String, Object> pmWbsInfo, String parentCode)
            Map<String, Object> pmWbsInfo = cbbPmWbsEntity.convertToMap();
            if(nodeList.size()>0){
                taskService.changeTaskByFlow(cbbPmWbsEntity.getProjectuucode(),nodeList,pmWbsInfo,parentCode, flowInsId);
            }
        }
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:创建wbs校验
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void createWbsSon(Map<String, Object> paraMap, CbbPmWbsEntity pmWbsEntity, String parentCode) {
        // 如果是子流程，找到主流程wbs
//            SELECT task.CODE AS parentCode,wbs.* FROM CBB_PM_WBS wbs
//            LEFT JOIN CBB_PM_TASK task ON wbs.PROJECTUUCODE = task.PROJECTUUCODE AND wbs.WBSCODE = TASK .WBSCODE
//            WHERE WBS .PROJECTUUCODE = ''

    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:创建wbs校验
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void createWbs(Map<String, Object> paraMap, CbbPmWbsEntity pmWbsEntity) {
        // 如果没传必传参数，告诉原函数返回空
        if(!paraMap.containsKey("uuCode") && !paraMap.containsKey("flowId")
                && !paraMap.containsKey("sourceId") && !paraMap.containsKey("sourceType")) {
            throw new NullPointerException("必传参数未传！");
        }
        String flowId = ConvertUtil.convertToString(paraMap.get("flowId"));
        String sourceId = ConvertUtil.convertToString(paraMap.get("sourceId"));
        String sourceType = ConvertUtil.convertToString(paraMap.get("sourceType"));
        String uuCode = ConvertUtil.convertToString(paraMap.get("uuCode"));
        StringBufferProxy sql = new StringBufferProxy();
        // 查找对应审批流
        sql.appendSingle("FLOWID = '{0}' and SOURCEID = '{1}' and SOURCETYPE = '{2}'",
                flowId,sourceId,sourceType);
        List<CboApprovalFlowInsEntity> flowInsEntities = cboApprovalFlowInsService.queryByWhere(sql.toString());
        if(flowInsEntities.size()==0){
            throw new NullPointerException("未找到对应审批流！");
        }
        String flowInsId = flowInsEntities.get(0).getId()+"";
        pmWbsEntity.setProjectuucode(uuCode);
        sql.clear();
        sql.appendSingle("{0} = '{1}' order by {2} DESC",CbbPmWbsChangeEntity.FieldProjectuucode,uuCode,CbbPmWbsChangeEntity.FieldAfterversion);
        List<CbbPmWbsChangeEntity> cbbPmWbsChangeEntities = cbbPmWbsChangeService.queryByWhere(sql.toString());
        if(cbbPmWbsChangeEntities.size() > 0){
            pmWbsEntity.setVersion(cbbPmWbsChangeEntities.get(0).getAfterversion());
        } else {
            pmWbsEntity.setVersion(1);
        }
        pmWbsEntity.setFlowid(flowId);
        pmWbsEntity.setFlowinsid(flowInsId);
        pmWbsEntity.setFlowinsstate(flowInsEntities.get(0).getState());
        long[] arrayId = PrimaryKeyUtil.GeneIDs(pmWbsEntity.getTableName(), 1);
        pmWbsEntity.setId(arrayId[0]);
        pmWbsEntity.setWbscode(PmSystemConst.CodePrefix.WBS+arrayId[0]);
        cbbPmWbsService.insert(pmWbsEntity);
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:任务变更--约束条件
     * @modify:
     */
    public void changeTaskByCommit(List<FlowNode> nodeList, Map<String, Object> paraMap){
        // 同步执行
        List<FlowNode> syncNodeList = nodeList.stream().filter( e -> (PmSystemConst.NodeRunType.SYNC.equals(e.getRuntype()))).collect(Collectors.toList());
        // 异步执行
        nodeList.removeAll(syncNodeList);

    }

    /**
     * @author: hudeyong
     * @date: 2023-06-26
     * @description:初始化任务
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void initTask(Map<String, Object> paraMap, CbbPmWbsEntity pmWbsEntity, String parentCode, int loopTimes, int useTimes) {
        String flowinsid = ConvertUtil.convertToString(paraMap.get("flowInsId"));
        // 节点list
        List<FlowNode> nodeList = queryWbsNodeList(paraMap);
        // 同步执行
        List<FlowNode> syncNodeList = nodeList.stream().filter( e -> (PmSystemConst.NodeRunType.SYNC.equals(e.getRuntype()))).collect(Collectors.toList());
        // 异步执行
        nodeList.removeAll(syncNodeList);
        taskService.initFlowTask(paraMap, syncNodeList,pmWbsEntity.convertToMap(),parentCode,flowinsid,true,loopTimes,useTimes);
        // 异步执行
        CbbPmWbsEntity finalPmWbsEntity = pmWbsEntity;
        String finalParentCode = parentCode;
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 在这里执行耗时操作
                taskService.initFlowTask(paraMap, nodeList, finalPmWbsEntity.convertToMap(), finalParentCode,flowinsid,true,loopTimes,useTimes);
            }
        }).start();
    }

    /**
    * @author: hudeyong
    * @date: 2023-06-13
    * @description:获取流程List
    * @modify:
    */
    @Override
    public List<FlowNode> queryWbsNodeList(Map<String, Object> paraMap){
        // 改为线程安全的list
        List<FlowNode> resultList = new ArrayList<>();
        String flowId = ConvertUtil.convertToString(paraMap.get("flowId"));
        StringBufferProxy querySql = new StringBufferProxy();
        // 查询有效的节点和线
        querySql.appendSingle("enabled = 1 and  FLOWID = '{0}'",flowId);
        List<Map<String, Object>> lineList = cboApprovalLineService.queryMapByWhere(querySql.toString());
        querySql.appendSingle(" order by NODETYPE");
        List<Map<String, Object>> nodeList = cboApprovalNodeService.queryMapByWhere(querySql.toString());
        ////////////////////////
        dealQueryCondition(paraMap,nodeList);
        String startNodeId = ConvertUtil.convertToString(paraMap.get("startNodeId"));
        String endNodeId = ConvertUtil.convertToString(paraMap.get("endNodeId"));
        String sourceId = ConvertUtil.convertToString(paraMap.get("sourceId"));
        String sourceType = ConvertUtil.convertToString(paraMap.get("sourceType"));
        boolean includeStart = ConvertUtil.convertToBoolean(paraMap.get("includeStart"));
        // 节点执行状态
        Map<String, Integer> nodeStates = new HashMap<>();
        Map<String, String> runTypeMap = new HashMap<>();
        for (int i = 0; i < nodeList.size(); i++) {
            // 添加编号
            nodeList.get(i).put(INDEX, i);
            // 初始化所有节点状态为未知状态-1,
            String nodeId = nodeList.get(i).get("id").toString();
            nodeStates.put(nodeId, PmSystemConst.TaskRuningState.UNKNOWN);
            // 初始化异步
            runTypeMap.put(nodeId, PmSystemConst.NodeRunType.NOSYNC);
        }
        // 开始和结束默认确认执行
        nodeStates.put(startNodeId, PmSystemConst.TaskRuningState.VALID);
        nodeStates.put(endNodeId, PmSystemConst.TaskRuningState.VALID);
        // 所有的节点ID与节点map
        Map<Long, Map<String, Object>> nodeIdMap = nodeList.stream().collect(Collectors.toMap(n -> ConvertUtil.convertToLong(n.get(CboApprovalNodeEntity.FieldId)), Function.identity()));
        Map<Integer, Map<String, Object>> indexToNodeMap = nodeList.stream().collect(Collectors.toMap(n -> ConvertUtil.convertToInt(n.get(INDEX)), Function.identity()));
        Map<Long, List<Map<String, Object>>> fromNodeIdMap = lineList.stream().collect(Collectors.groupingBy(l -> ConvertUtil.convertToLong(l.get(CboApprovalLineEntity.FieldFromnodeid))));
        // 获取所有线路
        List<List<Integer>> graph = new LinkedList<>();
        nodeList.forEach(node -> {
            List<Map<String, Object>> toLineList = fromNodeIdMap.get(MapUtil.getLong(node, CboApprovalNodeEntity.FieldId));
            List<Integer> list = CollUtil.defaultIfEmpty(toLineList, Collections.emptyList()).stream()
                    .map(line -> MapUtil.getLong(line, CboApprovalLineEntity.FieldTonodeid))
                    .map(toNodeId -> MapUtil.getInt(nodeIdMap.get(toNodeId), INDEX))
                    .collect(Collectors.toList());
            graph.add(list);
        });
        // 获取所有线是否可走
        queryIsPassLine(lineList,sourceId,sourceType);
        // 获取所有节点可执行状态
        queryIsPassNode(graph,indexToNodeMap,lineList,nodeStates,runTypeMap,startNodeId,endNodeId);
        List<Map<String, Object>> tempNodeList = new ArrayList<>();
        for(Map<String, Object> node : nodeList) {
            String nodeid = ConvertUtil.convertToString(node.get("id"));
            String nodeType = ConvertUtil.convertToString(node.get("nodetype"));
            // 只要不是开始、结束、分支、合并类型的 + 传入开始至传入结束的
            if(!PmSystemConst.NodeType.START.equals(nodeType)
                    && !PmSystemConst.NodeType.END.equals(nodeType)
                    && !PmSystemConst.NodeType.MERGE.equals(nodeType)
                    && !PmSystemConst.NodeType.BRANCH.equals(nodeType) && nodeStates.containsKey(nodeid)) {
                tempNodeList.add(node);;
            }
        }
        nodeList = tempNodeList;
        // 返回结果  获取人的方法
        Map<String, List<Map<String, Object>>> nodeApprovalUser = queryIsPassNodeUser(nodeList,nodeStates,paraMap);
        for(Map<String, Object> node : nodeList){
            String approvalparam = ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldApprovalparam));
            boolean isSonFlow = false;
            Map<String, Object> paramMap = new HashMap<>();
            if (!approvalparam.isEmpty()) {
                approvalparam = StrUtil.replace(approvalparam, StrUtil.CR, " ");
                approvalparam = StrUtil.replace(approvalparam, StrUtil.LF, " ");
                paramMap = JSONUtil.parseObj(approvalparam);
                if(paramMap.containsKey("excludeTask")){
                    continue;
                }
                isSonFlow = paramMap.containsKey("isSonFlow") && ConvertUtil.convertToBoolean(paramMap.get("isSonFlow"));
            }
            String nodeId = ConvertUtil.convertToString(node.get("id"));
            FlowNode flowNode = new FlowNode();
            flowNode.setPlanUser(nodeApprovalUser.get(nodeId));
            flowNode.setRuningState(nodeStates.get(nodeId));
            flowNode.setNodetype(isSonFlow ? PmSystemConst.NodeType.SONFLOW : ConvertUtil.convertToString(node.get("nodetype")));
            flowNode.setSortCode(ConvertUtil.convertToInt(node.get(CboApprovalNodeEntity.FieldSortcode)));
            flowNode.setName(ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldName)));
            //同步执行还是异步执行
            flowNode.setRuntype(runTypeMap.get(nodeId));
            flowNode.setId(nodeId);
            flowNode.setApprovalParam(paramMap);
            resultList.add(flowNode);
        }
        // 如果不包含开始节点，去除
        if(!includeStart) {
            return resultList.stream().filter(item -> !item.getId().equals(startNodeId)).collect(Collectors.toList());
        }
        return resultList;
    }

    public Map<String, List<Map<String, Object>>> queryIsPassNodeUser(List<Map<String, Object>> nodeList, Map<String, Integer> nodeStates, Map<String, Object> paraMap) {
        Map<String, List<Map<String, Object>>> resultMap = new ConcurrentHashMap<>();
        String sourceId = ConvertUtil.convertToString(paraMap.get("sourceId"));
        String sourceType = ConvertUtil.convertToString(paraMap.get("sourceType"));
        nodeList.parallelStream().forEach(node -> {
            try {
                List<String> userId = new ArrayList<>();
                String nodeId = ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldId));
                String nodeType = ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldNodetype));
                long planUserId = ConvertUtil.convertToLong(node.get(CboApprovalNodeEntity.FieldPlanuserid));
                String expStr = ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldPlanuserexp));
                // 节点参数
                boolean isSonFlow = false;
                String approvalparam = ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldApprovalparam));
                if(!approvalparam.isEmpty()){
                    approvalparam = StrUtil.replace(approvalparam, StrUtil.CR, " ");
                    approvalparam = StrUtil.replace(approvalparam, StrUtil.LF, " ");
                    Map<String, Object> paramMap = JSONUtil.parseObj(approvalparam);
                    isSonFlow = paramMap.containsKey("isSonFlow") && ConvertUtil.convertToBoolean(paramMap.get("isSonFlow"));
                }
                if(isSonFlow){
                    // 如果是子流程，不要责任人
                    nodeType = PmSystemConst.NodeType.SONFLOW;
                } else if (PmSystemConst.NodeType.CIRCULATION.equals(nodeType)) {
                    // 如果是自循环
                    userId = getAutoLoopNodeUser(expStr,sourceId, sourceType);
                } else if(planUserId>0) {
                    // 如果配置了应办理人
                    userId.add(planUserId+"");
                } else if(!expStr.isEmpty()) {
                    // 如果配置了办理人表达式
                    expStr = StrUtil.replace(expStr, StrUtil.CR, " ");
                    expStr = StrUtil.replace(expStr, StrUtil.LF, " ");
                    JSONArray exps = JSONUtil.parseArray(expStr);
                    JSONObject exp = exps.getJSONObject(0);
                    String sql = exp.getStr("Sql");
//                    sql = StrUtil.replaceIgnoreCase(sql, "{NI:flowinsid}", "1");
                    sql = StrUtil.replaceIgnoreCase(sql, "{NI:sourcetype}", sourceType);
                    sql = StrUtil.replaceIgnoreCase(sql, "{NI:sourceid}", sourceId);
                    List<Map<String, Object>> userList = cbbPmWbsService.selectExecute(sql);
                    for(Map<String, Object> userInfo : userList){
                        userId.add(ConvertUtil.convertToString(userInfo.get("id")));
                    }
                }
                FlowNode flowNode = new FlowNode();
                flowNode.setNodetype(nodeType);
                // 审批人员信息
                List<Map<String, Object>> approvalUserList = new ArrayList<>();
                String userIds = userId.stream().map(s -> "\'" + s + "\'").collect(Collectors.joining(","));
//                System.out.println(planUserId+"----"+node.get("name")+"----"+userIds);
                if (userIds.length() > 0) {
                    List<String> filedList = new ArrayList<>();
                    filedList.add("id");
                    filedList.add(CboUserEntity.FieldName + " as name");
                    filedList.add(CboUserEntity.FieldCode + " as code");
                    StringBufferProxy sql = new StringBufferProxy();
                    sql.appendSingle("id in ({0})", userIds);
                    approvalUserList = cboUserService.queryMapFieldsByWhere(sql.toString(), filedList);
                }
                resultMap.put(nodeId,approvalUserList);
            } catch (Exception e) {
                log.error("determine user error: {}", e.getMessage(), e);
            }
        });
        //
        return resultMap;
    }

        /**
         * @author: hudeyong
         * @date: 2023-06-13
         * @description:处理查询参数
         * @modify:
         */
    public void dealQueryCondition(Map<String, Object> paraMap, List<Map<String, Object>> nodeList){
        // 开始节点
        List<Map<String, Object>> tempList =
                nodeList.stream().filter(s -> PmSystemConst.NodeType.START.equals(ConvertUtil.convertToString(s.get("nodetype")))).collect(Collectors.toList());
        if(!paraMap.containsKey("startNodeId") && tempList.size() > 0){
            paraMap.put("startNodeId",tempList.get(0).get("id"));
        }
        // 结束节点
        tempList = nodeList.stream().filter(s -> PmSystemConst.NodeType.END.equals(ConvertUtil.convertToString(s.get("nodetype")))).collect(Collectors.toList());
        if(!paraMap.containsKey("endNodeId") && tempList.size() > 0){
            paraMap.put("endNodeId",tempList.get(0).get("id"));
        }
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-13
     * @description: 查询每条线是否可走
     * @modify:
     */
    public void queryIsPassLine(List<Map<String, Object>> lineList, String sourceId, String sourceType){
        lineList.parallelStream().forEach(line -> {
            try {
                // 找线上的条件
                String expStr = ConvertUtil.convertToString(line.get(CboApprovalLineEntity.FieldCondition));
                if (!expStr.isEmpty()) {
                    // 如果线上有条件
                    expStr = StrUtil.replace(expStr, StrUtil.CR, " ");
                    expStr = StrUtil.replace(expStr, StrUtil.LF, " ");
                    JSONArray conditions = JSONUtil.parseArray(expStr);
                    JSONObject jsonObject = conditions.getJSONObject(0);
                    String sql = jsonObject.getStr("Sql");
                    sql = StrUtil.replaceIgnoreCase(sql, "{NI:sourceid}", sourceId);
                    sql = StrUtil.replaceIgnoreCase(sql, "{NI:sourcetype}", sourceType);
//                    Integer go = cbbPmWbsService.selectCountExecute(sql);
                    List<Map<String,Object>> res = cbbPmWbsService.selectExecute(sql);
                    if (res != null && res.size() > 0) {
                        int go = ConvertUtil.convertToInt(res.get(0).get("res"));
                        line.put(PmSystemConst.ConstName.LINEPASSSTATE,go == 1 ? true : false);
                    } else {
                        line.put(PmSystemConst.ConstName.LINEPASSSTATE,false);
                    }
                    System.out.println(res);
//                    line.put(PmSystemConst.ConstName.LINEPASSSTATE,(go != null && go == 1) ? true : false);
                } else {
                    // 如果线上没条件，假定会走
                    line.put(PmSystemConst.ConstName.LINEPASSSTATE,true);
                }
            } catch (Exception e) {
                log.error("error: {}", e.getMessage(), e);
            }
        });
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-13
     * @description: 获取所有节点通行状态
     * @modify:
     */
    public void queryIsPassNode(List<List<Integer>> graph, Map<Integer, Map<String, Object>> indexToNodeMap, List<Map<String, Object>> lineList, Map<String, Integer> nodeStatesMap, Map<String, String> runTypeMap, String startNodeId, String endNodeId){
        List<List<Integer>> allPaths = new Solution().allPathsSourceTarget(graph);
        // 添加计数，每个node在每条线中走的次数
        Map<String, Integer> nodeIndexMap = new HashMap<>();
        Iterator<Map.Entry<String, Integer>> iterator = nodeStatesMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = iterator.next();
            nodeIndexMap.put(entry.getKey(),0);
        }
        AtomicInteger atomicInteger = new AtomicInteger();
        allPaths.stream()
                .map(route -> route.stream().map(indexToNodeMap::get).map(node -> ConvertUtil.convertToString(node.get(CboApprovalNodeEntity.FieldId))).collect(Collectors.toList()))
                .forEach(route -> {
//                    System.out.println(route);
                    int startIndex = route.indexOf(startNodeId);
                    int endIndex = route.indexOf(endNodeId);
                    if (startIndex >= 0 && endIndex >= 0 && startIndex < endIndex) {
                        List<String> subListToRemove = route.subList(0, startIndex);
                        subListToRemove.clear();
                        subListToRemove = route.subList(endIndex - startIndex + 1, route.size());
                        subListToRemove.clear();
                    } else {
                        return;
                    }
                    atomicInteger.getAndIncrement();
                    // 当前的最高级别是sure，表示都会走runStateMap
                    int level= PmSystemConst.TaskRuningState.VALID;
                    // 遍历这个线路，判断每个节点是否会走
                    boolean key = false;
                    int index = 1;
                    if(route.size()>0 && startNodeId.equals(route.get(0))){
                        key = true;
                    }
                    boolean endLoop = false;
                    for (int i = 1; i < route.size(); i++) {
                        String nowNodeId = route.get(i);
                        // 该节点走过一次，加一次计数
                        nodeIndexMap.put(nowNodeId,nodeIndexMap.get(nowNodeId) + 1);
                        if(endLoop){
                            continue;
                        }
                        if(startNodeId.equals(nowNodeId)){
                            key = true;
                        }
                        // 前三个同步执行，其余异步执行
                        if(key && index<=2) {
                            index++;
                            runTypeMap.put(nowNodeId, PmSystemConst.NodeRunType.SYNC);
                        }
                        // 找到这条线路中当前节点的前一个节点及关联的确定走的线
                        String beforeNodeId = route.get(i-1);
                        List<Map<String, Object>> tempLineList = lineList.stream().filter(s ->
                                s.get(CboApprovalLineEntity.FieldFromnodeid).toString().equals(beforeNodeId) &&
                                        s.get(CboApprovalLineEntity.FieldTonodeid).toString().equals(nowNodeId)).collect(Collectors.toList());
                        // 如果有这条线
                        if (tempLineList.size()>0) {
                            System.out.println(tempLineList.get(0).get("dispfromnodeid") +" —— "+tempLineList.get(0).get("disptonodeid") + tempLineList.get(0).get(PmSystemConst.ConstName.LINEPASSSTATE));
                            boolean linePassState = ConvertUtil.convertToBoolean(tempLineList.get(0).get(PmSystemConst.ConstName.LINEPASSSTATE));
                            if(linePassState){
                                // 如果这条线会走，那么这个节点是确定的
                                nodeStatesMap.put(nowNodeId,level);
                            } else {
                                // 如果这条线不会走，看看上一个节点其他线有没有确定的
                                // 如果有，说明这个节点是失效的，如果没有，说明这个节点是待定的
                                tempLineList = lineList.stream().filter(s -> beforeNodeId.equals(ConvertUtil.convertToString(s.get(CboApprovalLineEntity.FieldFromnodeid))) && ConvertUtil.convertToBoolean(s.get(PmSystemConst.ConstName.LINEPASSSTATE))).collect(Collectors.toList());
                                int state = nodeStatesMap.get(nowNodeId);
                                if(tempLineList.size()>0){
                                    // 有其他有效，说明有其他线路，这条线走不通了，没有必要继续了
                                    nodeStatesMap.put(nowNodeId,state > PmSystemConst.TaskRuningState.LOSE ? state : PmSystemConst.TaskRuningState.LOSE);
                                    endLoop = true;
                                } else {
                                    // 没有其他有效，上节点指向的都是待确定的，所以以后最高级别就是待确定
                                    level = state > PmSystemConst.TaskRuningState.CONFUSION ? state : PmSystemConst.TaskRuningState.CONFUSION;
                                    nodeStatesMap.put(nowNodeId,level);
//                                    level = PmSystemConst.TaskRuningState.CONFUSION;
                                }
                            }
                        }
                    }
                    System.out.println("===route===end===");
                });
        int routeNums = atomicInteger.get();
        iterator = nodeIndexMap.entrySet().iterator();;
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = iterator.next();
            if(entry.getValue() == routeNums) {
                nodeStatesMap.put(entry.getKey(), PmSystemConst.TaskRuningState.VALID);
            }
        }
        // 剩余是-1的都删除
        iterator = nodeStatesMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> entry = iterator.next();
            if (entry.getValue() == -1) {
                iterator.remove();
            }
        }
    }

    /**
     * @author: hudeyong
     * @date: 2023-06-14
     * @description: 获取自循环节点的审批人
     * @modify:
     */
    public List<String> getAutoLoopNodeUser(String scriptContent, String sourceId, String sourceType){
        List<String> userIdsList = new ArrayList<>();
        List<Map<String, String>> listMapScript = (List<Map<String, String>>) com.topscomm.pub.util.JSONUtil
                .parseJSONString(scriptContent);
        Map<String, String> mapScript = listMapScript.get(0);
        if (!mapScript.containsKey("InitSql")) {
            return userIdsList;
        }
        int stepLen = ConvertUtil.convertToInt(mapScript.get("StepLen"));
        String extCol = ConvertUtil.convertToString(mapScript.get("ExtCol"));
        int beginLen = ConvertUtil.convertToInt(mapScript.get("BeginLen"));
        int endLen = ConvertUtil.convertToInt(mapScript.get("EndLen"));
        String initSql = ConvertUtil.convertToString(mapScript.get("InitSql"));
        String queryUserIdSql = ConvertUtil.convertToString(mapScript.get("QueryUserIdSql"));
        //需要执行脚本从业务表获取
        initSql = StrUtil.replaceIgnoreCase(initSql, "{NI:sourceid}", sourceId);
        initSql = StrUtil.replaceIgnoreCase(initSql, "{NI:sourcetype}", sourceType);
        List<Map<String, Object>> listDataMap = cbbPmWbsService.selectExecute(initSql);
        if(listDataMap.size()==0){
            return userIdsList;
        }
        String extColValue = String.valueOf(listDataMap.get(0).get(listDataMap.get(0).keySet().toArray()[0]));
        // 如果部门长度大于开始长度
        String deptcodes = "";
        if (extColValue.length() > beginLen) {
            extColValue = extColValue.substring(0, beginLen);
            for(int i = beginLen; i>= endLen; i = i-stepLen){
                deptcodes = deptcodes + "'" + extColValue + "',";
                extColValue = extColValue.substring(0, extColValue.length()-stepLen);
            }
        }
        if(deptcodes.length()==0){
            return userIdsList;
        }
        deptcodes = deptcodes.substring(0,deptcodes.length()-1);
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("SELECT DISTINCT HEADERIDS as userid FROM CBODEPT WHERE CODE IN ({0}) AND HEADERIDS != 0",deptcodes);
        List<Map<String, Object>> deptList = cbbPmWbsService.selectExecute(sql.toString());
        for(Map<String, Object> header : deptList){
            userIdsList.add(ConvertUtil.convertToString(header.get("userid")));
        }
        // 提交人
        queryUserIdSql = StrUtil.replaceIgnoreCase(queryUserIdSql, "{NI:sourceid}", sourceId);
        queryUserIdSql = StrUtil.replaceIgnoreCase(queryUserIdSql, "{NI:sourcetype}", sourceType);
        List<Map<String, Object>> tempList = cbbPmWbsService.selectExecute(queryUserIdSql);
        if(tempList.size()>0){
            userIdsList.remove(tempList.get(0).get("id"));
        }
        return userIdsList;
    }


}
